package com.borrowed.book.weixin.WxUtil;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

public class WxUtil {

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 日期格式化
     * @param date
     * @param parseStr
     * @return
     */
    public static String DateToStr(Date date, String parseStr){
        String dateStr="";
        try{
            SimpleDateFormat sdf=new SimpleDateFormat(parseStr);
            dateStr=sdf.format(date);
        }catch (Exception e){
            e.printStackTrace();
        }
        return dateStr;
    }


    /**
     * 处理返回对象
     *
     * @param request
     * @return
     */
    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line; (line = br.readLine()) != null; ) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * v3 支付异步通知验证签名
     *
     * @param body 异步通知密文
     * @param key  api 密钥
     * @return 异步通知明文
     * @throws Exception 异常信息
     */
    public static String verifyNotify(String body, String key) throws Exception {
        // 获取平台证书序列号
        JSONObject resultObject = JSONObject.parseObject(body);
        JSONObject resource = resultObject.getJSONObject("resource");
        String cipherText = resource.getString("ciphertext");//Base64编码后的授权/解除授权结果数据密文。
        String nonceStr = resource.getString("nonce");//加密使用的随机串。
        String associatedData = resource.getString("associated_data");//附加数据
        String algorithm=resource.getString("algorithm");//对授权结果数据进行加密的加密算法，
        AesUtil aesUtil = new AesUtil(key.getBytes(StandardCharsets.UTF_8));
        // 密文解密
        return aesUtil.decryptToString(
                associatedData.getBytes(StandardCharsets.UTF_8),
                nonceStr.getBytes(StandardCharsets.UTF_8),
                cipherText
        );
    }

    /**
     * 获取httpClient
     * @param mchId
     * @param mchSerialNo
     * @return
     * @throws IOException
     */
    public  static HttpClient getHttpClient(String mchId,String mchSerialNo,String apiV3Key) throws IOException {
        File directory = new File("..");// 参数为空
        String courseFile = directory.getCanonicalPath()+"/apiclient_key.pem";
        PrivateKey privateKey=getPrivateKey(courseFile);

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3秘钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, privateKey)),apiV3Key.getBytes("utf-8"));
        // 初始化httpClient
        HttpClient httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, privateKey).withValidator(new WechatPay2Validator(verifier)).build();

        return httpClient;
    }


    /**
     * 生成退款号
     * @return
     */
    public static String CreateOutRefundNo(){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
        String shu= RandomStringUtils.randomAlphanumeric(4);
        String outRefundNo = "TK"+sdf.format(new Date()) + shu;
        return outRefundNo;
    }
}
